package trikita.talalarmo;

import android.app.Activity;
import android.os.Bundle;

import android.content.Intent;
import android.app.PendingIntent;
import android.app.AlarmManager;

import android.view.View;
import android.view.Window;
import android.widget.Toast;
import android.widget.TextView;
import android.widget.FrameLayout;

import android.view.MenuItem;
import android.view.MenuInflater;
import android.view.Menu;

import android.graphics.Typeface;
import android.os.Handler;
import java.util.Calendar;

import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.net.Uri;

import android.util.Log;

/** Activity where alarm time and settings are set */
public class TalalarmoActivity extends Activity
	implements ClockView.OnAlarmSetListener {

	private final static String tag = "TalalarmoActivity";
	/** Delay for showing notification about set alarm time */
	private final static long NOTIFICATION_DELAY_TIME = 2 * 1000;

	/** Prefernce activity result code */
	private final static int PREFS_UPDATED = 100;

	public final static String PREFS_NAME = "TalalarmoSharedPreferences";
	

	private ClockView mClock;				// hours circle
	private TextView mStartTv;					// alarm salutation
	private FrameLayout mContainerLayout;		// container for all the views

	/* mToastRunnable display user notification to know how long 
	 	alarm sleeps until it goes off. Toast must be shown after some delay
		(NOTIFICATION_DELAY_TIME) since the last user's manipulations has been made. 
		Handler has been created to manage this */
	private Handler mShowToastHandler = new Handler();
	private Runnable mToastRunnable = new Runnable() {
		@Override
		public void run() {
			// Do nothing
		}
	};

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.act_main);

		Typeface t = Typeface.createFromAsset(getAssets(),
				"fonts/font.ttf");
		
		mContainerLayout = (FrameLayout) findViewById(R.id.l_container);

		mStartTv = (TextView) findViewById(R.id.tv_invite);
		mStartTv.setTypeface(t);

		mClock = (ClockView) findViewById(R.id.v_hours);

		// Activity should be informed when alarm is set to deal with this event
		mClock.setOnAlarmSetListener(this);

		// Restore last set time of an alarm from the SharedPreferences
		SharedPreferences prefs = getSharedPreferences(PREFS_NAME, 0);
		mClock.setTime(prefs.getInt("hour", 8), prefs.getInt("minute", 0));
		mClock.setChecked(prefs.getBoolean("daytime", true));

		// Detect if alarm has been set - then show clock views,
		// otherwise - invite to make the alarm working
		if (prefs.getBoolean("is_alarm_on", false)) {
			mContainerLayout.setPadding(0, 0, 0, 0);
			mStartTv.setVisibility(View.GONE);
		}
		// Adjust colorscheme to the current set time
		updateColorScheme();

		// Abnormal manipulation to fix issue:
		// when the user launches application first, starts up the alarm clock
		// and doesn't pick any sound in settings - nothing sounds when alarm will go off.
		// And it really works!
		SharedPreferences defPref = PreferenceManager.getDefaultSharedPreferences(this);
		String ringtone = defPref.getString("ringtone_pref", 
			Settings.System.DEFAULT_RINGTONE_URI.toString());
		Uri uri = Uri.parse(ringtone);
		if (uri.equals(Settings.System.DEFAULT_RINGTONE_URI)) {
			defPref.edit().putString("ringtone_pref", 
					Settings.System.DEFAULT_RINGTONE_URI.toString()).commit();
		}
		mClock.setSnap(defPref.getBoolean("snap_pref", true));
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.options_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			// Disable alarm, show invitation
			case R.id.om_stop:
				mContainerLayout.setPadding(0, 0, 0, 0);
				mStartTv.setVisibility(View.VISIBLE);
				stopRepeating();
				break;
			// Start PreferenceActivity
			case R.id.om_prefs:
				Intent intent = new Intent(getBaseContext(),
						Preferences.class);
				startActivityForResult(intent, PREFS_UPDATED);
				break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
			case PREFS_UPDATED:
				SharedPreferences prefs =
					PreferenceManager.getDefaultSharedPreferences(this);
				mClock.setSnap(prefs.getBoolean("snap_pref", true));
				break;
		}
	}

	@Override 
	protected void onPause() {
		super.onPause();
		// We need an Editor object to make preference changes.
		// All objects are from android.context.Context
		SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
		SharedPreferences.Editor editor = settings.edit();

		// Save alarm time 
		editor.putInt("hour", mClock.getTime()[0]);
		editor.putInt("minute", mClock.getTime()[1]);
		editor.putBoolean("daytime", mClock.isChecked());
		editor.putBoolean("is_alarm_on", mStartTv.getVisibility() == View.GONE);

		// Commit the edits!
		editor.commit();
	}

	/** Called when you tap on screen to start alarm.
	 * Callback for click on TextView that fill the whole display.
	 * Set in xml file of the current layout.
	 */
	public void showAlarm(View v) {
		Log.d(tag, "TEXTVIEW ONCLICK");
		// Hide invitation to alarm 
		v.setVisibility(View.GONE);
		mContainerLayout.setPadding(10, 10, 10, 10);
		
		// By default if there are no any user manipulations the alarm 
		// will be set for the time shown on clock views
		setAlarm(mClock.getTime()[0], mClock.getTime()[1]);
	}

	/** Callback for am/pm toggling event */
	@Override
	public void switchAMPM() {
		updateColorScheme();
//		// Now alarm time will be changed too
		setAlarm(mClock.getTime()[0], mClock.getTime()[1]);
	}

	private void updateColorScheme() {
		FrameLayout layout = (FrameLayout) findViewById(R.id.l_container);	
		// White background of layout if the SwitchButton in "AM" state,
		// black - otherwise.
		layout.setBackgroundColor(mClock.isChecked() ? ClockView.WHITE : ClockView.BLACK);

	}

	/** Callback for alarm set event.
	 *  Called when some time passed since the time value 
	 *  had been set for any of the alarm ClockViews */
	@Override
	public void onSetTime(ClockView v, int timeHour, int timeMin) {
//		int hour = 0;
//		int minute = 0;
		// Check if the user set minutes or hours
//		switch (v.getId()) {
//			case R.id.v_hours:
//				hour = time;
//				minute = mMinutesClock.getTime();
//				break;
//			case R.id.v_minutes:
//				hour = mHoursClock.getTime();
//				minute = time;
//				break;
//		}

		final int h = timeHour;
		final int m = timeMin;

		mShowToastHandler.removeCallbacks(mToastRunnable);
		mToastRunnable = new Runnable() {
			@Override
			public void run() {
				setAlarm(h, m);
			}
		};
		mShowToastHandler.postDelayed(mToastRunnable, NOTIFICATION_DELAY_TIME);
	}

	@Override
	public void onProceedSetTime() {
		mShowToastHandler.removeCallbacks(mToastRunnable);
	}

	/** Calculates time period for an alarm and starts up alarm clock */
	private void setAlarm(int hour, int minute) {
		// Convert to 24-format of hours representation
		hour = (mClock.isChecked() ? (hour % 12) : (hour % 12) + 12);

		// Create the Calendar instance for the current system time
		long now = System.currentTimeMillis();
		Calendar current = Calendar.getInstance();
		current.setTimeInMillis(now);

		// Create the Calendar instance for the alarm clock time
		// for the current date
		Calendar alarm = (Calendar) current.clone();  
		alarm.set(Calendar.HOUR_OF_DAY, hour);
		alarm.set(Calendar.MINUTE, minute);
		alarm.set(Calendar.SECOND, 0);

		// If the alarm clock time value in millis is less than 
		// the current time in the same format - then add to the alarm
		// Calendar instance one day
		if (current.getTimeInMillis() > alarm.getTimeInMillis()) {
			alarm.add(Calendar.DAY_OF_MONTH, 1);
		}

		// Calculate time period and when it passes the alarm clock will go off
		long delay = alarm.getTimeInMillis() - current.getTimeInMillis();
		final int hours = (int) ((delay / (1000 * 60 * 60)) % 24);
		final int minutes = (int) ((delay / (1000 * 60)) % 60);

		Log.d(tag, "Alarm is set on "+alarm.get(Calendar.DAY_OF_MONTH)+" at "+
				alarm.get(Calendar.HOUR)+":"+alarm.get(Calendar.MINUTE));

		// And of course don't forget to stop working alarm clock
		stopRepeating();
		// before you start up the new alarm
		startRepeating(alarm);

		// Inform the user when he has to wake up
		mShowToastHandler.removeCallbacks(mToastRunnable);
		mToastRunnable = new Runnable() {
			@Override
			public void run() {
				Toast.makeText(TalalarmoActivity.this, "Alarm will go off in "
						+hours+" hours and "+minutes+" minutes.",
						Toast.LENGTH_LONG).show();
					
			}
		};
		mShowToastHandler.postDelayed(mToastRunnable, NOTIFICATION_DELAY_TIME);
	}

	/** Actually starts up the alarm clock - send PendingIntent for 
	 * the BroadcastReceiver that will be called when alarm goes off */
	private void startRepeating(Calendar alarmTime) {
		Log.d(tag, "Start repeating");
		// When the alarm goes off, we want to broadcast an Intent to our
		// BroadcastReceiver.  Here we make an Intent with an explicit class
		// name to have our own receiver (which has been published in
		// AndroidManifest.xml) instantiated and called, and then create an
		// IntentSender to have the intent executed as a broadcast.
		// Note that unlike above, this IntentSender is configured to
		// allow itself to be sent multiple times.
		Intent intent = new Intent(this, AlarmReceiver.class);
		PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, 0);

		// Schedule the alarm!
		AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
		am.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime.getTimeInMillis(),
				(24 * 60 * 60 * 1000), sender);
	}

    private void stopRepeating() {
		Log.d(tag, "Stop repeating");
		// Create the same intent, and thus a matching IntentSender, for
		// the one that was scheduled
		Intent intent = new Intent(this, AlarmReceiver.class);
		PendingIntent sender = PendingIntent.getBroadcast(this,
				0, intent, 0);

		// And cancel the alarm
		AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
		am.cancel(sender);
	}
}

